/*******************************************************************************************************
Copyright (C) 2021 Mestrelab Research S.L. All rights reserved.

This file is part of the Mnova scripting toolkit.

Authorized users of Mnova Software may use this file freely, but this file is provided AS IS
with NO WARRANTY OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE.
*****************************************************************************************************/

/*globals FileDialog, settings, File, MessageBox, serialization, mainWindow, Dir, TextStream, Document, MnUi,
Application, Molecule, NMRSpectrum, mnMessage, mnError, mnInfo*/
/*jslint plusplus: true, continue: true, bitwise: true*/

function openACDASV() {
	"use strict";

	var i, contents, singleContents, aContent, spectraPath, aSDFFilePath, currentFile, file, currentDir, nthSDFFile,
		sdfFilePathKey = "Open ACD ASV/Last Opened ACD ASV File";

	aSDFFilePath = FileDialog.getOpenFileName("*.sdf", "Open sdf File with ACD ASV data", settings.value(sdfFilePathKey, Dir.home()));
	if (aSDFFilePath) {
		settings.setValue(sdfFilePathKey, aSDFFilePath);
		file = new File(aSDFFilePath);
		openACDASV.writeLog("Converting file " + aSDFFilePath + " to Mnova documents", 1);
		currentFile = aSDFFilePath.slice(1 + file.absDirPath.length, aSDFFilePath.lastIndexOf("."));
		currentDir = new Dir(file.absDirPath);
		contents = openACDASV.readFile(aSDFFilePath);
	}

	if (contents) {
		serialization.history = false;
		singleContents = contents.split("$$$$");
		for (i = 0; i < singleContents.length; i++) {
			aContent = singleContents[i];
			if (aContent.indexOf(">  <CHEMICAL_SHIFTS") !== -1) {
				aContent += "\n$$$$\n";
				nthSDFFile = currentDir.filePath(currentFile + "_" + i + ".sdf");
				openACDASV.writeFile(aContent, nthSDFFile);
				if (!spectraPath) { //Spectra are common to all SDF Files
					spectraPath = openACDASV.extractSpectraPath(nthSDFFile);
					openACDASV.writeLog("Spectra files declared in SDF: " + JSON.stringify(spectraPath), 1);
					//correctedSpectraPaths = openACDASV.correctPaths(spectraPath, currentDir);
					//openACDASV.writeLog("Spectra files found in the same directory of SDF: " + JSON.stringify(correctedSpectraPaths), 1);
				}
				openACDASV.createMnovaFile(spectraPath, nthSDFFile);
				File.remove(nthSDFFile);
			}
		}
		serialization.history = true;
	}
}


openACDASV.createMnovaFile = function (paths, aSDFFile) {
	"use strict";

	var i, aMolecule, aSpectrum, aPath, lastSpectrumIndex,
		outputFilePath = aSDFFile.replace(".sdf", ".mnova"),
		aDoc = mainWindow.newDocument();

	serialization.history = false;

	if (serialization.open(aSDFFile)) {
		openACDASV.writeLog("SDF " + aSDFFile + " imported: ", 1);
		aMolecule = new Molecule(aDoc.item(0, "Molecule"));
		serialization.save(outputFilePath, "mnova");
	} else {
		openACDASV.writeLog("Failed to open SDF " + aSDFFile, 2);
	}

	openACDASV.writeLog("Importing NMR spectra ...", 1);
	for (i = 0; i < paths.length; i++) {
		aPath = paths[i];
		openACDASV.writeLog("  opening file " + aPath, 1);
		if (aPath && File.exists(aPath)) {
			if (serialization.open(aPath)) {
				openACDASV.writeLog("    file " + aPath + " opened", 1);
				lastSpectrumIndex = aDoc.itemCount("NMR Spectrum") - 1;
				aSpectrum = new NMRSpectrum(aDoc.item(lastSpectrumIndex, "NMR Spectrum"));
				aMolecule.linkItems("Assignments", aSpectrum);
				serialization.save(outputFilePath, "mnova");
			} else {
				openACDASV.writeLog("    failed to open file " + aPath, 2);
			}
		}
	}
	aDoc.close();
	serialization.history = true;
};


openACDASV.correctPaths = function (paths, aDir) {
	"use strict";

	var i, j, aPath, dirContents, bestIndex, commonPathEnd, bestCommonPathEnd,
		correctPaths = [];

	openACDASV.writeLog("Detecting local copies of spectra files ...", 1);
	for (i = 0; i < paths.length; i++) {
		aPath = paths[i];
		openACDASV.writeLog("  original file: " + aPath, 1);
		if (!File.exists(aPath)) {
			bestCommonPathEnd = "";
			bestIndex = undefined;
			dirContents = this.getDirContents(aDir, []);
			for (j = 0; j < dirContents.length; j++) {
				commonPathEnd = openACDASV.getCommonPathEnd(aPath, dirContents[j], true);
				if (commonPathEnd && commonPathEnd.length > bestCommonPathEnd.length) {
					bestIndex = j;
					bestCommonPathEnd = commonPathEnd;
				}
			}
			correctPaths[i] = dirContents[bestIndex];
			openACDASV.writeLog("    best match found: " + dirContents[bestIndex], 1);
		}
	}

	return correctPaths;
};


openACDASV.getCommonPathEnd = function (aRefPath, aPath, useUpperCase) {
	"use strict";

	var i, splittedPath, splittedRefPath, maxLength, ref, test, firstCommonEndIndex, endPathArray;

	if (useUpperCase) {
		aRefPath = aRefPath.toUpperCase();
		aPath = aPath.toUpperCase();
	}

	splittedRefPath = aRefPath.split("/");
	splittedPath = aPath.split("/");
	maxLength = Math.max(splittedPath.length, splittedRefPath.length);

	for (i = 0; i < maxLength; i++) {
		ref = splittedRefPath[splittedRefPath.length - 1 - i];
		test = splittedPath[splittedPath.length - 1 - i];
		if (test === ref) {
			firstCommonEndIndex = i;
		} else {
			break;
		}
	}
	if (firstCommonEndIndex !== undefined) {
		endPathArray = splittedPath.splice(splittedPath.length - 1 - firstCommonEndIndex, splittedPath.length);
		return endPathArray.join("/");
	}
};


openACDASV.getDirContents = function (aDirPath, aContents) {
	"use strict";

	var i, dir, dirs,
		contents = aContents || [];

	dir = new Dir(aDirPath);
	dirs = dir.entryInfoList("*", Dir.All | Dir.NoDotAndDotDot, Dir.Time);
	for (i = 0; i < dirs.length; i++) {
		if (dirs[i].isDir) {
			contents = this.getDirContents(dirs[i].toString(), contents);
		} else {
			contents.push(dirs[i].absoluteFilePath);
		}
	}
	return contents;
};


openACDASV.readFile = function (filename) {
	"use strict";

	var stream,
		file = new File(filename);
	try {
		file.open(File.ReadOnly);
		stream = new TextStream(file);
		stream.codec = "UTF-8";
		return (stream).readAll();
	} catch (err) {
		MessageBox.warning(err);
	} finally {
		file.close();
	}
};


openACDASV.writeFile = function (aText, aFilePath) {
	"use strict";

	var stream, aFile;

	aFile = new File(aFilePath);
	aFile.open(File.WriteOnly);
	stream = new TextStream(aFile);
	stream.write(aText);
	stream.flush();
	aFile.close();
};


openACDASV.extractSpectraPath = function (aSDFPath) {
	"use strict";

	var j, k, aMolecule, tags, tagName, tagContent, aPath, tagLines, aLine, paths,
		doc = new Document();

	serialization.history = false;
	Application.lockDocument(doc);
	serialization.open(aSDFPath);
	aMolecule = new Molecule(doc.item(0, "Molecule"));
	if (aMolecule.isValid()) {
		tags = aMolecule.sdfNames();
		paths = [];
		for (j = 0; j < tags.length; j++) {
			tagName = tags[j];
			if (tagName.endsWith("_SpectrumParameters")) {
				tagContent = aMolecule.getSDFData(tagName);
				tagLines = tagContent.split("\n");
				for (k = 0; k < tagLines.length; k++) {
					aLine = tagLines[k];
					if (aLine.startsWith("File Name")) {
						aPath = aLine.replace("File Name", "").trim().replace(/\\/g, "/");
						paths.push(aPath);
					}
				}
			}
		}
	}
	doc.destroy();
	Application.unlockDocument(doc);
	serialization.history = true;

	return paths;
};


openACDASV.writeLog = function (aMessage, aLevel) {
	"use strict";

	var tag = "OpenACDASV: ",
		levels = ["Info", "Message", "Error"];

	if (aLevel === levels[1]) {
		mnMessage(tag + aMessage);
	} else if (aLevel === this.errorLevel) {
		mnError(tag + aMessage);
	} else {
		mnInfo(tag + aMessage);
	}
};


if (this.MnUi && this.MnUi.scripts_nmr) {
	MnUi.scripts_nmr.scripts_nmr_Convert_ACD_ASV = openACDASV;
}
